package com.skivingcloud.admin.security;

import com.mybatisflex.core.query.QueryWrapper;
import com.skivingcloud.admin.sys.entity.SysPersistentLogins;
import com.skivingcloud.admin.sys.service.SysPersistentLoginsService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.dao.IncorrectResultSizeDataAccessException;
import org.springframework.security.web.authentication.rememberme.PersistentRememberMeToken;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
import org.springframework.stereotype.Service;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Date;

/**
 * @author hushouquan
 */
@Service("myTokenRepository")
public class MyTokenRepositoryImpl implements PersistentTokenRepository{
    protected final Logger logger = LoggerFactory.getLogger(this.getClass());
    private SysPersistentLoginsService sysPersistentLoginsService;

    public MyTokenRepositoryImpl(SysPersistentLoginsService sysPersistentLoginsService) {
        this.sysPersistentLoginsService = sysPersistentLoginsService;
    }

    @Override
    public void createNewToken(PersistentRememberMeToken token){
        SysPersistentLogins sysPersistentLogins = new SysPersistentLogins();
        sysPersistentLogins.setUsername(token.getUsername());
        sysPersistentLogins.setSeries(token.getSeries());
        sysPersistentLogins.setToken(token.getTokenValue());
        Instant instant = token.getDate().toInstant();
        ZoneId zoneId = ZoneId.systemDefault();
        LocalDateTime localDateTime = instant.atZone(zoneId).toLocalDateTime();
        sysPersistentLogins.setLastUsed(localDateTime);
        sysPersistentLoginsService.save(sysPersistentLogins);
    }
    
    @Override
    public void updateToken(String series, String tokenValue, Date lastUsed){
        SysPersistentLogins sysPersistentLogins = new SysPersistentLogins();
        sysPersistentLogins.setSeries(series);
        sysPersistentLogins.setToken(tokenValue);
        Instant instant = lastUsed.toInstant();
        ZoneId zoneId = ZoneId.systemDefault();
        LocalDateTime localDateTime = instant.atZone(zoneId).toLocalDateTime();
        sysPersistentLogins.setLastUsed(localDateTime);
        sysPersistentLoginsService.updateById(sysPersistentLogins);
    }
    
    @Override
    public PersistentRememberMeToken getTokenForSeries(String seriesId){
        try {
            SysPersistentLogins sysPersistentLogins = sysPersistentLoginsService.getById(seriesId);
            if(sysPersistentLogins == null){
                return null;
            }
            ZoneId zoneId = ZoneId.systemDefault();
            ZonedDateTime zdt = sysPersistentLogins.getLastUsed().atZone(zoneId);
            Date date = Date.from(zdt.toInstant());
            return new PersistentRememberMeToken(sysPersistentLogins.getUsername(), sysPersistentLogins.getSeries(), sysPersistentLogins.getToken(), date);
        } catch (EmptyResultDataAccessException var3) {
            logger.error("Querying token for series '{}' returned no results.", seriesId, var3);
        } catch (IncorrectResultSizeDataAccessException var4) {
            logger.error("Querying token for series '{}' returned more than one value. Series should be unique", seriesId, var4);
        } catch (DataAccessException var5) {
            logger.error("Failed to load token for series {}", seriesId, var5);
        }
        return null;
    }
    
    @Override
    public void removeUserTokens(String username){
        QueryWrapper wrapper = QueryWrapper.create().where(SysPersistentLogins::getUsername).eq(username);
        sysPersistentLoginsService.remove(wrapper);
    }
}
